#ifndef LEXICALUNITIMPL_H_INCLUDED_XAIRY
#define LEXICALUNITIMPL_H_INCLUDED_XAIRY

#include "LexicalUnit.h"

class LexicalUnitImpl : public LexicalUnit
{
public:
	virtual LexicalUnitType getLexicalUnitType()const;
	virtual LexicalUnit* getNextLexicalUnit()const;
	virtual LexicalUnit* getPreviousLexicalUnit()const;

	virtual int getIntegerValue()const;
	virtual float getFloatValue()const;

	virtual string getDimensionUnitText()const;
	virtual string getFunctionName()const;

	virtual LexicalUnit* getParameters()const;
	virtual string getStringValue()const;
	virtual LexicalUnit* getSubValues()const;

	virtual const string* toString()const;

public:
	inline void setLexicalUnitType(LexicalUnitType type)
	{
		m_UnitType = type;
	}

	inline void setNextLexicalUnit(LexicalUnit* next)
	{
		nextLexicalUnit = next;
	}

	inline void setPreviousLexicalUnit(LexicalUnit* pre)
	{
		previousLexicalUnit = pre;
	}

	inline void setFloatValue(float _floatval)
	{
		floatvalue = _floatval;
	}

	inline void setDimension(const string& dim)
	{
		if(dimension)
		{
			delete dimension;
			dimension = NULL;
		}
		dimension = new string(dim);
	}

	inline void setFunctionName(const string& function)
	{
		if(functionName)
		{
			delete functionName;
			functionName = NULL;
		}
		functionName = new string(function);
	}

	inline void setParameters(LexicalUnit* params)
	{
		if(parameters)
		{
			delete parameters;
			parameters = NULL;
		}
		parameters = params;
	}

	inline void setStringValue(const string& _stringValue)
	{
		if(stringValue)
		{
			delete stringValue;
			stringValue = NULL;
		}
		stringValue = new string(_stringValue);
	}

public:
	virtual ~LexicalUnitImpl();

public:
	static LexicalUnit* createNumber(LexicalUnit* prev, int i)
	{
        return new LexicalUnitImpl(prev, i);
    }

	static LexicalUnit* createNumber(LexicalUnit* prev, float f)
	{
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_REAL, f);
    }

    static LexicalUnit* createPercentage(LexicalUnit* prev, float f)
	{
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_PERCENTAGE, f);
    }

    static LexicalUnit* createPixel(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_PIXEL, f);
    }

    static LexicalUnit* createCentimeter(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_CENTIMETER, f);
    }

    static LexicalUnit* createMillimeter(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_MILLIMETER, f);
    }

    static LexicalUnit* createInch(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_INCH, f);
    }

    static LexicalUnit* createPoint(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_POINT, f);
    }

	static LexicalUnit* createPica(LexicalUnit* prev, float f)
	{
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_PICA, f);
    }

    static LexicalUnit* createInherit(LexicalUnit* prev)
    {
    	return new LexicalUnitImpl(prev, LexicalUnit::SAC_INHERIT, "inherit");
    }

    static LexicalUnit* createEm(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_EM, f);
    }

    static LexicalUnit* createEx(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_EX, f);
    }

    static LexicalUnit* createDegree(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_DEGREE, f);
    }

    static LexicalUnit* createRadian(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_RADIAN, f);
    }

    static LexicalUnit* createGradian(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_GRADIAN, f);
    }

    static LexicalUnit* createMillisecond(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_MILLISECOND, f);
    }

	static LexicalUnit* createSecond(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_SECOND, f);
    }

    static LexicalUnit* createHertz(LexicalUnit* prev, float f)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_HERTZ, f);
    }

    static LexicalUnit* createDimension(LexicalUnit* prev, float f, const string& dim)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_DIMENSION, dim, f);
    }

	static LexicalUnit* createKiloHertz(LexicalUnit* prev, float f)
	{
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_KILOHERTZ, f);
    }

    static LexicalUnit* createCounter(LexicalUnit* prev, LexicalUnit* params)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_COUNTER_FUNCTION,
								   "counter", params);
    }

    static LexicalUnit* createCounters(LexicalUnit* prev, LexicalUnit* params)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_COUNTERS_FUNCTION,
								  "counters", params);
    }

    static LexicalUnit* createAttr(LexicalUnit* prev, LexicalUnit* params)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_ATTR, "attr", params);
    }

    static LexicalUnit* createRect(LexicalUnit* prev, LexicalUnit* params)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_RECT_FUNCTION,
								   "rect", params);
    }

    static LexicalUnit* createRgbColor(LexicalUnit* prev, LexicalUnit* params)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_RGBCOLOR, "rgb", params);
    }

    static LexicalUnit* createFunction(LexicalUnit* prev, const string& name,
									   LexicalUnit* params)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_FUNCTION, name, params);
    }

    static LexicalUnit* createString(LexicalUnit* prev, const string& value)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_STRING_VALUE, value);
    }

    static LexicalUnit* createIdent(LexicalUnit* prev, const string& value)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_IDENT, value);
    }

    static LexicalUnit* createURI(LexicalUnit* prev, const string& value)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_URI, value);
    }

    static LexicalUnit* createComma(LexicalUnit* prev)
    {
        return new LexicalUnitImpl(prev, LexicalUnit::SAC_OPERATOR_COMMA);
    }

    static LexicalUnit* createSlash(LexicalUnit* prev)
    {
    	return new LexicalUnitImpl(prev, LexicalUnit::SAC_OPERATOR_SLASH);
    }

protected:
	LexicalUnitImpl(LexicalUnit* pre, LexicalUnitType type);
	LexicalUnitImpl(LexicalUnit* pre, int value);
	LexicalUnitImpl(LexicalUnit* pre, LexicalUnitType type, float value);
	LexicalUnitImpl(LexicalUnit* pre, LexicalUnitType type,
					const string& dim, float value);
	LexicalUnitImpl(LexicalUnit* pre, LexicalUnitType type,
					const string& value);
	LexicalUnitImpl(LexicalUnit* pre, LexicalUnitType type,
					const string& name, LexicalUnit* params);
	LexicalUnitImpl();

private:
	string trimFloat(float f)const;
	void appendParams(string& s, const LexicalUnit* first)const;

private:
	LexicalUnitType m_UnitType;
	float floatvalue;
	string* dimension;
	string* functionName;
	LexicalUnit* parameters;
	string* stringValue;

	LexicalUnit* previousLexicalUnit;
	LexicalUnit* nextLexicalUnit;
};

#endif // LEXICALUNITIMPL_H_INCLUDED_XAIRY
